/* qust
 * 基于promise与ES6简易封装的XHR库
 * @Jan
 * @Version 2021-0413
 */

class Utils {
	isArray(val) {
		return toString.call(val) === "[object Array]";
	}
	isObject(val) {
		return val !== null && typeof val === "object";
	}
	isPlainObject(val) {
		if (toString.call(val) !== "[object Object]") {
			return false;
		}
		var prototype = Object.getPrototypeOf(val);
		return prototype === null || prototype === Object.prototype;
	}
	forEach(obj, fn) {
		if (obj === null || typeof obj === "undefined") {
			return;
		}
		if (typeof obj !== "object") {
			obj = [obj];
		}
		if (this.isArray(obj)) {
			for (var i = 0, l = obj.length; i < l; i++) {
				fn.call(null, obj[i], i, obj);
			}
		} else {
			for (var key in obj) {
				if (Object.prototype.hasOwnProperty.call(obj, key)) {
					fn.call(null, obj[key], key, obj);
				}
			}
		}
	}
	// 深度合并对象
	merge() {
		var result = {};
		function assignValue(val, key) {
			if (this.isPlainObject(result[key]) && this.isPlainObject(val)) {
				result[key] = this.merge(result[key], val);
			} else if (this.isPlainObject(val)) {
				result[key] = this.merge({}, val);
			} else if (this.isArray(val)) {
				result[key] = val.slice();
			} else {
				result[key] = val;
			}
		}

		for (var i = 0, l = arguments.length; i < l; i++) {
			this.forEach(arguments[i], assignValue.bind(this));
		}
		return result;
	}
}

class Qust extends Utils {
	constructor(arg) {
		super();
		let defaultInstanceConfig = {
			baseUrl: "",
			header: {},
		};
		this.config = super.merge(defaultInstanceConfig, arg);
	}

	create(arg) {
		return new Qust(arg);
	}

	request(arg) {
		let defaultRequestConfig = {
			method: "POST",
			data: null,
			url: "",
		};
		let sendConfig = super.merge(defaultRequestConfig, arg);
		return new Promise((resolve, reject) => {
			let xhr = new XMLHttpRequest();

			// 填充数据
			xhr.open(sendConfig.method, this.config.baseUrl + sendConfig.url, true);

			// 设置header
			for (let key in this.config.header) {
				xhr.setRequestHeader(key, this.config.header[key]);
			}

			// 发送
			xhr.send(sendConfig.data);

			// 处理回调
			xhr.onreadystatechange = () => {
				if (xhr.readyState === 4) {
					if (xhr.status === 200) {
						resolve({
							code: xhr.status,
							data: JSON.parse(xhr.responseText),
						});
					} else {
						reject({
							code: xhr.status,
						});
					}
				}
			};
		});
	}
}

export default new Qust();
